package net.nyancofc.piconnow;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import net.nyancofc.piconnow.tweet.AddressManager;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.protocol.HTTP;

import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;

import android.app.ActivityManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.location.Location;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.widget.Toast;

public class PiconNowTwitterPostService
	extends Service {

	private static final String TAG = "PiconNowTwitterPostService";

    private IPiconNowGPSManageService binder;

	private CommonsHttpOAuthConsumer consumer;
	private Location lastLocation;

    private Handler handler=new Handler();
    private boolean running=false;

    //Debug Flag
    boolean useDummyLocation = true;
    boolean doNotPost = false;

    private Intent     serviceIntent;

    int accuracyThreashold = 100;

    int tweetInterval = 30;
    int lookAheadTime = 20;
    private static int iTime;

    private static NotificationManager nm;

    LogManager m_log;
    Thread thread;

    ArrayList<String> logList;

    private class LogManager {
    	public synchronized void write(String messages) {
    		Date datetime = new Date();  //(1)Dateオブジェクトを生成

    	    SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    	    logList.add(sdf1.format(datetime) + ":" + messages);
    	}
    }

    //サービス生成時に呼ばれる
    @Override
    public void onCreate() {
        logList = new ArrayList<String>();
        m_log = new LogManager();
        toast(PiconNowTwitterPostService.this,"onCreate called!");
        super.onCreate();
		running = true;
    }

    //サービス開始時に呼ばれる
    @Override
    public void onStart(Intent intent,int startID) {
        super.onStart(intent,startID);

        //ノティフィケーションの表示
        showNotification(this,R.drawable.icon,
            "Picon Nowを開始しました",
            "Picon Now",
            "Picon Now管理画面を開きます");

        //サービスインテントの生成
        serviceIntent=new Intent();
        serviceIntent.setClassName("net.nyancofc.piconnow",
            "net.nyancofc.piconnow.PiconNowGPSManageService");
        //サービスの接続
        if (isServiceRunning("net.nyancofc.piconnow.PiconNowGPSManageService")) {
            bindService(serviceIntent,connection,BIND_AUTO_CREATE);
        }

        if (thread != null) {
        	thread.stop();
        }

        iTime = 0;

        thread=new Thread(){
            public void run() {
                running=true;
                while (running) {
                	if (tweetInterval - lookAheadTime < iTime) {
                        //サービスの開始
                        startService(serviceIntent);
                        //サービスの接続
                        bindService(serviceIntent,connection,BIND_AUTO_CREATE);
	                    handler.post(new Runnable(){
	                        public void run() {
	                        	m_log.write("access to gps service...");
	                            if (binder != null) {
		                        	try {
		                				lastLocation = binder.getGPSInfo();
		                			} catch (RemoteException e) {
		                				Log.e("error", e.getMessage());
		                				e.printStackTrace();
		                			}
	                            }
	                            if (lastLocation != null) {
	                            	m_log.write("gps accuracy:" + String.valueOf(lastLocation.getAccuracy()));
	                            	if (lastLocation.getAccuracy() < (float)accuracyThreashold) {
	                                	//toast(PiconNowTwitterPostService.this,"Main:"+"精度の高い情報が取れたのでございます。");
	                            	}
	                            }
	                        }
	                    });
                	}
                	if (iTime == tweetInterval) {
                        //サービスの切断
                        unbindService(connection);
                        //サービスの終了
                        stopService(serviceIntent);
                    	iTime = 0;
	                    handler.post(new Runnable(){
	                        public void run() {
		                    	AddressManager ad = new AddressManager();
		                    	address = ad.getAddressNameFromPosition(lastLocation);
                            	m_log.write("gps address:" + address);
		                    	tweet();
	                        }
	                    });
                	}
                	m_log.write(String.valueOf(iTime));
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                    }
                    iTime++;
                }
            }
        };
        thread.start();
    }


    //サービスが起動中かどうか
    private boolean isServiceRunning(String className) {
        ActivityManager am=(ActivityManager)getSystemService(ACTIVITY_SERVICE);
        List<ActivityManager.RunningServiceInfo> serviceInfos=
            am.getRunningServices(Integer.MAX_VALUE);
        for (int i=0;i<serviceInfos.size();i++) {
            if (serviceInfos.get(i).service.getClassName().equals(className)) {
                return true;
            }
        }
        return false;
    }

    //サービス停止時に呼ばれる
    @Override
    public void onDestroy() {
        running=false;
        //サービスの切断
        unbindService(connection);
        //サービスの停止
        stopService(serviceIntent);
        super.onDestroy();
    }

    //サービス接続時に呼ばれる
    @Override
    public IBinder onBind(Intent intent) {
    	Log.d(TAG, "onBind");
        return IPiconNowTwitterPostService;
    }

    @Override
    public boolean onUnbind(Intent intent) {
    	Log.d(TAG, "onUnbind");
        nm.cancel(0);
        binder=null;
        return super.onUnbind(intent);
    }

    //ノティフィケーションの表示
    private static void showNotification(Context context,
        int iconID,String ticker,String title,String message) {
        //ノティフィケーションオブジェクトの生成
        Notification notification=new Notification(iconID,
            ticker,System.currentTimeMillis());
        PendingIntent intent=PendingIntent.getActivity(context,0,
            new Intent(context,PiconNowActivity.class),0);
        notification.setLatestEventInfo(context,title,message,intent);

        //ノティフィケーションマネージャyの取得
        nm=(NotificationManager)
            context.getSystemService(Context.NOTIFICATION_SERVICE);

        //ノティフィケーションのキャンセル
        nm.cancel(0);

        //ノティフィケーションの表示
        nm.notify(0,notification);
    }

    //トーストの表示　
    private static void toast(Context context,String text) {
        Toast.makeText(context,text,Toast.LENGTH_SHORT).show();
    }

    //サービスバインダ
    private final IPiconNowTwitterPostService.Stub IPiconNowTwitterPostService=new IPiconNowTwitterPostService.Stub() {
        public void setConsumerInfo(String _token, String _stoken, String key, String skey) throws RemoteException {
            consumer=new CommonsHttpOAuthConsumer(key,skey);
            consumer.setTokenWithSecret(_token, _stoken);
       }
        public void checkLogList(List<String> in_logList) {
        	Iterator<String> itr = logList.iterator();
        	while (itr.hasNext()) {
        		in_logList.add(itr.next());
        		itr.remove();
        	}
       		return;
        }
    };

    //サービスコネクション
    private ServiceConnection connection=new ServiceConnection() {
        //サービス接続時に呼ばれる
        public void onServiceConnected(ComponentName name,IBinder service) {
        	Log.d(TAG, "onServiceConnected");
            binder=IPiconNowGPSManageService.Stub.asInterface(service);
        }

        //サービス切断時に呼ばれる
        public void onServiceDisconnected(ComponentName name) {
        	Log.d(TAG, "onServiceDisconnected");
            nm.cancel(0);
            binder=null;
        }
    };

	private String address;

	public void tweet() {
		if (lastLocation != null) {
			tweetAddress();
			tweetPosition();
		} else {
			Log.d(TAG, "位置情報が取れてないのです。ポスト処理をスキップするのです。");
		}
    }

	/**
	 * 位置情報をつぶやく
	 */
	private void tweetAddress() {
		double speed = lastLocation.getSpeed() * 3.6;
		String message = "Picon Now α版テストちゅ。";
		if (useDummyLocation) {
			address = "ほったらかし温泉（検証のため）";
		}
		UpdateTwitter(message + " 現在、"+address+"あたりを" + Math.round(speed*10)/10.0 + "km/hで、ぬーん。");
	}

	/**
	 * 座標情報をつぶやく
	 */
	private void tweetPosition() {
		StringBuffer geoCodingAddr = new StringBuffer("http://www.geocoding.jp/?q=");
		if (useDummyLocation) {
			geoCodingAddr.append("N").append("35.70604");
			geoCodingAddr.append("+");
			geoCodingAddr.append("E").append("138.65206");
		} else {
			geoCodingAddr.append("N").append(Math.round(lastLocation.getLatitude()*100000)/100000.0);
			geoCodingAddr.append("+");
			geoCodingAddr.append("E").append(Math.round(lastLocation.getLongitude()*100000)/100000.0);
		}
		UpdateTwitter(geoCodingAddr.toString());
	}

	/**
	 * Twitterへつぶやく
	 * @param str
	 * 投稿内容
	 */
	private synchronized void UpdateTwitter( String str){
    	HttpResponse response = null;
        try {
        	if (consumer != null) {
	            HttpPost post=new HttpPost("http://twitter.com/statuses/update.xml");
	            final List<NameValuePair> params=new ArrayList<NameValuePair>();
	            params.add(new BasicNameValuePair("status",(new Date()).toString() + str));
	            if (useDummyLocation) {
	            	params.add(new BasicNameValuePair("lat","35.70604"));
	            	params.add(new BasicNameValuePair("long","138.65206"));
	            } else {
	            	params.add(new BasicNameValuePair("lat", Double.toString((Math.round(lastLocation.getLatitude()*100000)/100000.0))));
	            	params.add(new BasicNameValuePair("long",Double.toString((Math.round(lastLocation.getLongitude()*100000)/100000.0))));
	            }
	            post.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
	            post.getParams().setBooleanParameter(
	                CoreProtocolPNames.USE_EXPECT_CONTINUE,false);
	            consumer.sign(post);
	            DefaultHttpClient http=new DefaultHttpClient();
	            if (doNotPost == false) {
	            	response = http.execute(post);
	            } else {
	            	toast(PiconNowTwitterPostService.this,"post処理したいけど、デバッグ中のため禁止されています。");
	            }
        	}
        } catch (Exception e) {
        	toast(PiconNowTwitterPostService.this, e.getMessage());
        } finally {
        	toast(PiconNowTwitterPostService.this,"post処理完了");
        }
	}


}
